#include "e042a13.h"
#include "spi_port.h"

static void epaper_commad_w(unsigned char command)
{
    spi_delay(1);
    EPD_W21_CS_0;
    EPD_W21_DC_0; // command write
    spi_write(command);
    EPD_W21_CS_1;
}

static void epaper_data_w(unsigned char command)
{
    spi_delay(1);
    EPD_W21_CS_0;
    EPD_W21_DC_1;
    spi_write(command);
    EPD_W21_CS_1;
}

static void e4v2_e042a13_readbusy(void)
{
    while (1) { //=1 BUSY
        if (isEPD_W21_BUSY == 0)
            break;
    }
}

static void e4v2_update(void)
{
    epaper_commad_w(0x22); // Display Update Control
    epaper_data_w(0xC7);
    epaper_commad_w(0x20); // Activate Display Update Sequence
    e4v2_e042a13_readbusy();
}

int e4v2_e042a13_init(void)
{
    epd_power_on();
    epd_delay_ms(40);
    EPD_W21_RST_0; // Module reset
    epd_delay_ms(10);

    EPD_W21_RST_1;
    epd_delay_ms(10);

    e4v2_e042a13_readbusy(); // waiting for the electronic paper IC to release the idle


    epaper_commad_w(0x12); // SWRESET
    e4v2_e042a13_readbusy(); // waiting for the electronic paper IC to release the idle

    epaper_commad_w(0x74);
    epaper_data_w(0x54);
    epaper_commad_w(0x7E);
    epaper_data_w(0x3B);
    epaper_commad_w(0x2B); // Reduce glitch under ACVCOM
    epaper_data_w(0x04);
    epaper_data_w(0x63);

    epaper_commad_w(0x0C); // Soft start setting
    epaper_data_w(0x8B);
    epaper_data_w(0x9C);
    epaper_data_w(0x96);
    epaper_data_w(0x0F);

    epaper_commad_w(0x01); // Set MUX as 300
    epaper_data_w(0x2B);
    epaper_data_w(0x01);
    epaper_data_w(0x00);

    epaper_commad_w(0x11); // Data entry mode
    epaper_data_w(0x01);
    epaper_commad_w(0x44);
    epaper_data_w(0x00); // RAM x address start at 0
    epaper_data_w(0x31); // RAM x address end at 31h(49+1)*8->400
    epaper_commad_w(0x45);
    epaper_data_w(0x2B); // RAM y address start at 12Bh
    epaper_data_w(0x01);
    epaper_data_w(0x00); // RAM y address end at 00h
    epaper_data_w(0x00);
    epaper_commad_w(0x3C); // board
    epaper_data_w(0x01); // HIZ

    epaper_commad_w(0x18);
    epaper_data_w(0X80);
    epaper_commad_w(0x22);
    epaper_data_w(0XB1); // Load Temperature and waveform setting.
    epaper_commad_w(0x20);
    e4v2_e042a13_readbusy(); // waiting for the electronic paper IC to release the idle
    epaper_commad_w(0x4E);
    epaper_data_w(0x00);
    epaper_commad_w(0x4F);
    epaper_data_w(0x2B);
    epaper_data_w(0x01);
    return 0;
}


int e4v2_e042a13_sleep(void)
{
    epaper_commad_w(0x10);
    epaper_data_w(0x01);
    epd_delay_ms(100);
    return 0;
}

int e4v2_e042a13_clean(void)
{
    unsigned int i;
    epaper_commad_w(0x24);
    for (i = 0; i < ALLSCREEN_GRAGHBYTES; i++) {
        epaper_data_w(0xff);
    }
    epaper_commad_w(0x26);
    for (i = 0; i < ALLSCREEN_GRAGHBYTES; i++) {
        epaper_data_w(0x00);
    }

    e4v2_update();
    return 0;
}

static uint8_t get_data(uint8_t * color, uint8_t pix_size)
{
    uint8_t data = 0;
    int i =0, j = 0;
    for (i = 0; i < 8; i++) {
        data = data | (color[j] << (7-i));
        j = j + pix_size;
    }
    return data;
}


int e4v2_e042a13_draw(uint8_t *wbuf, uint8_t pix_size, uint32_t hor_res, uint32_t ver_res)
{
    int i = 0, j = 0;
    uint8_t data;

    e4v2_e042a13_init();

    epaper_commad_w(0x24);
    for (i = ver_res - 1; i >=0  ; i--) {
        for (j = 0; j < hor_res; ) {
            data = get_data(&wbuf[j + i * hor_res * pix_size], pix_size);
            epaper_data_w(data);
            j = j + 8 * pix_size;
        }
    }
    e4v2_update();
    return 0;
}

int e4v2_e042a13_stop(void)
{
    epd_power_off();
    return 0;
}